import _ from 'lodash';

const pools = new Map();
const overwrites = new Map();

/**
 * 对象容器
 * @Author: wenjm 
 * @Date: 2018-03-27 13:59:57 
 * @Last Modified by: wenjm
 * @Last Modified time: 2018-09-27 18:00:24
 */
class Services {

    static test() {
        for (var key of pools.keys()) {
            console.log(key);
        }
    }

    /**
     * 获取/创建单例对象实例，慎重使用此方法（重载方法）
     * @method Services.getInstance(clazz)
     * @method Services.getInstance(clazz,[args])
     * @method Services.getInstance(key,clazz,[args])
     * @method Services.getInstance(prefix,key,clazz,[args])
     * @param prefix 唯一标识前缀
     * @param key 唯一标识
     * @param clazz 类
     * @param args 构造函数参数，数组
     */
    static getInstance() {
        let key;
        let clazz;
        let args;
        switch (arguments.length) {
            case 1:
                key = clazz = arguments[0];
                break;
            case 2:
                args = arguments[1];
                key = clazz = arguments[0];
                break;
            case 3:
                key = arguments[0];
                clazz = arguments[1];
                args = arguments[2];
                break;
            case 4:
                key = arguments[0] + "::" + arguments[1];
                clazz = arguments[2];
                args = arguments[3];
                break;
        }
        if (!key) {
            return undefined;
        }
        if (_.isString(key)) {
            key = key.toLowerCase();
        }
        if (!pools.has(key) && clazz) {
            if (overwrites.has(key)) {
                clazz = overwrites.get(key).clazz;
                args = args || overwrites.get(key).args;
            }
            if (args && !_.isArray(args)) {
                args = [args];
            }
            if (!_.isString(clazz)) {
                pools.set(key, Reflect.construct(clazz, args || []));
            }
        }
        return pools.get(key);
    }

    /**
     * 查询对象实例（重载方法）
     * @method Services.findInstance(clazzOrKey)
     * @method Services.findInstance(prefix,key)
     * @param prefix 唯一标识前缀
     * @param key 唯一标识
     * @param clazz 类
     */
    static findInstance() {
        let key;
        switch (arguments.length) {
            case 1:
                key = arguments[0];
                break;
            case 2:
                key = arguments[0] + "::" + arguments[1];
                break;
        }
        if (_.isString(key)) {
            key = key.toLowerCase();
        }
        return pools.get(key);
    }

    /**
     * 重写单例实例，慎重使用此方法（重载方法）
     * @method Services.overwrite(clazz,target)
     * @method Services.overwrite(clazzOrKey,target,[args])
     * @method Services.overwrite(prefix,key,target,[args])
     * @param prefix 唯一标识前缀
     * @param key 唯一标识
     * @param clazz 重写源类
     * @param target 重写目标类
     * @param args 构造函数参数，数组
     */
    static overwrite() {
        let key;
        let clazz;
        let args = [];
        switch (arguments.length) {
            case 2:
                key = arguments[0];
                clazz = arguments[1];
                break;
            case 3:
                key = arguments[0];
                clazz = arguments[1];
                args = arguments[2];
                break;
            case 4:
                key = arguments[0] + "::" + arguments[1];
                clazz = arguments[2];
                args = arguments[3];
                break;
        }
        if (_.isString(key)) {
            key = key.toLowerCase();
        }
        if (key && clazz && !overwrites.has(key)) {
            if (args && !_.isArray(args)) {
                args = [args];
            }
            overwrites.set(key, {
                clazz: clazz,
                args: args
            });
            return true;
        }
        return false;
    }

    /**
     * 设置对象实例，慎重使用此方法（重载方法）
     * @method Services.setInstance(clazzOrKey,instance)
     * @method Services.setInstance(prefix,key,instance)
     * @param prefix 唯一标识前缀
     * @param clazzOrKey 类或唯一标识
     * @param instance 对象示例
     */
    static setInstance() {
        let key;
        let instance;
        switch (arguments.length) {
            case 2:
                key = arguments[0];
                instance = arguments[1];
                break;
            case 3:
                key = arguments[0] + "::" + arguments[1];
                instance = arguments[2];
                break;
        }
        if (!key || !instance) {
            return false;
        }
        if (_.isString(key)) {
            key = key.toLowerCase();
        }
        pools.set(key, instance);
        return true;
    }

    /**
     * 创建对象实例，不存储到对象池，慎重使用此方法（重载方法）
     * @method Services.newInstance(clazz)
     * @method Services.newInstance(clazz,[args])
     * @method Services.newInstance(key,clazz,[args])
     * @method Services.newInstance(prefix,key,clazz,[args])
     * @param prefix 唯一标识前缀
     * @param key 唯一标识
     * @param clazz 类
     * @param args 构造函数参数，数组
     */
    static newInstance() {
        let key;
        let clazz;
        let args;
        switch (arguments.length) {
            case 1:
                key = clazz = arguments[0];
                break;
            case 2:
                args = arguments[1];
                key = clazz = arguments[0];
                break;
            case 3:
                key = arguments[0];
                clazz = arguments[1];
                args = arguments[2];
                break;
            case 4:
                key = arguments[0] + "::" + arguments[1];
                clazz = arguments[2];
                args = arguments[3];
                break;
        }
        if (!key || !clazz) {
            return undefined;
        }
        if (_.isString(key)) {
            key = key.toLowerCase();
        }
        if (overwrites.has(key)) {
            clazz = overwrites.get(key).clazz;
            args = args || overwrites.get(key).args;
        }
        return Reflect.construct(clazz, args || []);
    }

}
export default Services;